/*****************************************************************************
 * util.c: Miscellaneous routines functions
 *****************************************************************************
 * Copyright (C) 2010 Sam Grandjean
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <ctype.h>
#include <sys/time.h>

#include "util.h"

int str_count(const char *str, const int character)
{
	int total = 0;
	char *p;
	p = strchr(str, character);
	while (p != NULL) {
		p = strchr(p + 1, character);
		total++;
	}
	return total;
}

int file_size(const char *path)
{
	struct stat st;
	if (stat(path, &st) != 0) return 0;
	return st.st_size;
}

char* file_ext(char *path)
{
	static char ext[16] = "";
	char* peek = path + path[strlen(path) - 1];
	while (peek >= path) {
		if (*peek == '.') {
			strncpy(ext, peek + 1, sizeof(ext));
			break;
		}
		peek--;
	}
	return ext;
}

char* bytes_format(const unsigned long long size)
{
	static char str[10];
	// With unsigned long long max is 16.0 EB
	char units[9][6] = {"bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
	double s = (double) size;
	int count = 0;
	while ((s / 1024.0) > 0.5 && count < 8) {
		s = s / 1024.0;
		count++;
	}
	char format[6] = "";
	sprintf(format, "%%.%df ", (count == 0 ? 0 : (s < 10 ? 2 : (s < 100 ? 1 : 0))));
	sprintf(str, format, s);
	strncat(str, units[count], sizeof(units[count]));
	return str;
}

char* str_tolower(const char *str)
{
	static char res[255];
	int i = 0;
	char c;
	while (i < sizeof(res)) {
		if (str[i]) {
			c = str[i];
			res[i] = tolower(c);
		} else {
			res[i] = '\0';
		}
		i++;
	}
	return res;
}

double utime(struct timezone *tzp)
{
	struct timeval tv;
	gettimeofday(&tv, tzp);
	return (double) tv.tv_sec + (double) tv.tv_usec / 1.0e+6;
}

double bench(double utime, struct timezone *tzp)
{
	struct timeval tv;
	gettimeofday(&tv, tzp);
	return ((double) tv.tv_sec + (double) tv.tv_usec / 1.0e+6) - utime;
}

